package com.whmskj.xjlhsc.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.whmskj.xjlhsc.controller.vo.EfficiencyVo;
import com.whmskj.xjlhsc.entity.Sb02EquipmentCounterAccount;
import com.whmskj.xjlhsc.entity.Shachangsbbanyield;
import com.whmskj.xjlhsc.entity.Shachangsbhouryield;
import com.whmskj.xjlhsc.mapper.ScKbMapper;
import com.whmskj.xjlhsc.service.Sb02EquipmentCounterAccountService;
import com.whmskj.xjlhsc.service.ScKbService;
import com.whmskj.xjlhsc.service.ShachangsbhouryieldService;
import com.whmskj.xjlhsc.service.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;




@Service
@Slf4j
public class ScKbServiceImpl implements ScKbService {

    @Autowired
    private ScKbMapper scKbMapper;
    @Autowired
    private ShachangsbhouryieldService shachangsbhouryieldService;

    @Autowired
    private Sb02EquipmentCounterAccountService sb02EquipmentCounterAccountService;


    @Override
    public Object qfkbGet1() {
        DateTime date = DateUtil.date();
        String begin = DateUtil.beginOfDay(date).toString();
        String end = DateUtil.endOfDay(date).toString();
        return get(begin,end);
    }

    @Override
    public Object qfkbGet2() {
        DateTime date = DateUtil.date();
        String begin = DateUtil.beginOfMonth(date).toString();
        String end = DateUtil.endOfMonth(date).toString();
        return get(begin,end);
    }

    @Override
    public Object qfkbGet3() {
        DateTime date = DateUtil.date();
        String begin = DateUtil.beginOfDay(date).toString();
        String end = DateUtil.endOfDay(date).toString();
        List<String> allProcessList = Arrays.asList("梳棉","头并","条卷","精梳","末并","粗纱");
        LambdaQueryWrapper<Sb02EquipmentCounterAccount> sbLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sbLambdaQueryWrapper.in(Sb02EquipmentCounterAccount::getProcess, allProcessList);
        List<Sb02EquipmentCounterAccount> sbList = sb02EquipmentCounterAccountService.list(sbLambdaQueryWrapper);
        List<Integer> sbIds = sbList.stream().map(Sb02EquipmentCounterAccount::getId).toList();
        LambdaQueryWrapper<Shachangsbhouryield> shachangsbhouryieldLambdaQueryWrapper = new LambdaQueryWrapper<>();
        shachangsbhouryieldLambdaQueryWrapper.in(Shachangsbhouryield::getMesid, sbIds);
        shachangsbhouryieldLambdaQueryWrapper.between(Shachangsbhouryield::getDay, begin,end);
        List<Shachangsbhouryield> clList = shachangsbhouryieldService.list(shachangsbhouryieldLambdaQueryWrapper);
        List<Map<String, Object>> list = sbList.stream().map(item -> {
            double sum = clList.stream().filter(f -> f.getMesid().equals(item.getId())).mapToDouble(m -> NumberUtil.parseDouble(m.getActualyieldkg(), 0.0)).sum();
            Map<String, Object> map = new HashMap<>();
            map.put("process", item.getProcess());
            map.put("name", item.getDevicename());
            map.put("jth", item.getPlatform());
            map.put("date", date.toDateStr());
            map.put("bc", getBc());
            map.put("dbcl", sum);
            map.put("drcl", sum);
            return map;
        }).toList();
        return list;
    }

    @Override
    public Object hfkbGet1(String process) {
        LambdaQueryWrapper<Sb02EquipmentCounterAccount> sbLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sbLambdaQueryWrapper.eq(Sb02EquipmentCounterAccount::getProcess, process);
        List<Sb02EquipmentCounterAccount> sbList = sb02EquipmentCounterAccountService.list(sbLambdaQueryWrapper);
        return sbList.stream().map(item -> {
            Map<String, Object> map = new HashMap<>();
            map.put("process", item.getProcess());
            map.put("name", item.getDevicename());
            map.put("jth", item.getPlatform());
            map.put("xl", "0.00");
            return map;
        }).toList();
    }

    private String getBc(){
        LocalTime start = LocalTime.of(9, 30,0);
        LocalTime end = LocalTime.of(21, 30, 0);
        LocalTime now = LocalTime.now();
        return now.isAfter(start) && now.isBefore(end) ? "白班" : "夜班";
    }

    private Map<String,Object> get(String begin,String end){
        List<String> allProcessList = Arrays.asList("梳棉","头并","条卷","精梳","末并","粗纱");
        LambdaQueryWrapper<Sb02EquipmentCounterAccount> sbLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sbLambdaQueryWrapper.in(Sb02EquipmentCounterAccount::getProcess, allProcessList);
        List<Sb02EquipmentCounterAccount> sbList = sb02EquipmentCounterAccountService.list(sbLambdaQueryWrapper);
        List<Integer> sbIds = sbList.stream().map(Sb02EquipmentCounterAccount::getId).toList();
        LambdaQueryWrapper<Shachangsbhouryield> shachangsbhouryieldLambdaQueryWrapper = new LambdaQueryWrapper<>();
        shachangsbhouryieldLambdaQueryWrapper.in(Shachangsbhouryield::getMesid, sbIds);
        shachangsbhouryieldLambdaQueryWrapper.between(Shachangsbhouryield::getDay, begin,end);
        List<Shachangsbhouryield> clList = shachangsbhouryieldService.list(shachangsbhouryieldLambdaQueryWrapper);
        AtomicInteger atomicInteger = new AtomicInteger(1);
        List<Map<String, Object>> list = sbList.stream().filter(f -> f.getProcess().equals("梳棉")).map(item -> {
            double sum = clList.stream().filter(f -> f.getMesid().equals(item.getId())).mapToDouble(m -> NumberUtil.parseDouble(m.getActualyieldkg(), 0.0)).sum();
            Map<String, Object> map = new HashMap<>();
            map.put("pm", atomicInteger.getAndIncrement());
            map.put("name", item.getDevicename());
            map.put("jth", item.getPlatform());
            map.put("cl", sum);
            return map;
        }).toList();
        atomicInteger.setRelease(1);
        List<Map<String, Object>> list1 = sbList.stream().filter(f -> f.getProcess().equals("头并") ||
                f.getProcess().equals("条卷") || f.getProcess().equals("精梳") || f.getProcess().equals("末并")).map(item -> {
            double sum = clList.stream().filter(f -> f.getMesid().equals(item.getId())).mapToDouble(m -> NumberUtil.parseDouble(m.getActualyieldkg(), 0.0)).sum();
            Map<String, Object> map = new HashMap<>();
            map.put("pm", atomicInteger.getAndIncrement());
            map.put("name", item.getDevicename());
            map.put("jth", item.getPlatform());
            map.put("cl", sum);
            return map;
        }).toList();

        List<Map<String, Object>> list2 = sbList.stream().filter(f -> f.getProcess().equals("粗纱")).map(item -> {
            double sum = clList.stream().filter(f -> f.getMesid().equals(item.getId())).mapToDouble(m -> NumberUtil.parseDouble(m.getActualyieldkg(), 0.0)).sum();
            Map<String, Object> map = new HashMap<>();
            map.put("pm", atomicInteger.getAndIncrement());
            map.put("name", item.getDevicename());
            map.put("jth", item.getPlatform());
            map.put("cl", sum);
            return map;
        }).toList();
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("sm", list);
        resultMap.put("bt", list1);
        resultMap.put("cs", list2);
        return resultMap;
    }

    // 获取设备运行状态
    @Override
    public StatusCountDTO getStatusCount() {
        StatusCountDTO result = scKbMapper.countStatus();

        // 确保即使没有数据也返回0值
        if (result == null) {
            result = new StatusCountDTO();
        }

        return result;
    }

    /**
     * 获取设备效率
     *
     * @return
     */
    @Override
    public EfficiencyVo getEqumentEfficiency() {
        // 获取全部设备信息
        List<Shachangsbhouryield> sbList = scKbMapper.selectAll();
        // 获取sbList中所有不重复的车间信息
        List<String> workshops = sbList.stream()
                .map(Shachangsbhouryield::getWorkshop)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());

        // 获取最近7天的日期列表
        List<String> xAxisData = getDate();


        //  初始化效率数据存储结构
        Map<String, Map<String, EfficiencyData>> workshopEfficiencyMap = new HashMap<>();
        workshops.forEach(workshop -> {
            Map<String, EfficiencyData> dailyEfficiency = new LinkedHashMap<>();
            // 使用 "yyyy-MM-dd" 格式作为键
            xAxisData.forEach(date -> dailyEfficiency.put(date, new EfficiencyData()));
            workshopEfficiencyMap.put(workshop, dailyEfficiency);
        });

        // 调试日志：记录数据总量
        log.info("Total records: {}", sbList.size());

        // 处理原始数据，按车间和日期分组
        for (Shachangsbhouryield data : sbList) {
            if (StringUtils.isBlank(data.getWorkshop())) continue;

            // 获取原始日期（格式为 "yyyy-MM-dd"）
            String originalDate = data.getDay();
            if (originalDate == null || originalDate.length() < 10) continue;

            // 提取日期部分（前10个字符）
            String dateKey = originalDate.substring(0, 10);

            // 跳过不在最近7天范围内的数据
            if (!xAxisData.contains(dateKey)) continue;

            // 获取对应的EfficiencyData对象
            EfficiencyData ed = workshopEfficiencyMap.get(data.getWorkshop()).get(dateKey);
            if (ed == null) continue;

            try {
                BigDecimal theoretical = (data.getActualyieldkg() != null) ? new BigDecimal(data.getActualyieldkg()) : BigDecimal.ZERO;
                BigDecimal actual = (data.getActualyieldkg() != null) ? new BigDecimal(data.getActualyieldkg()) : BigDecimal.ZERO;

                ed.addTheoretical(theoretical);
                ed.addActual(actual);

                // 调试日志：记录添加的数据
                log.debug("Added data - Workshop: {}, Date: {}, Theoretical: {}, Actual: {}",
                        data.getWorkshop(), dateKey, theoretical, actual);

            } catch (NumberFormatException e) {
                log.error("Invalid yield data: ID={}, yield={}, actual={}",
                        data.getID(), data.getActualyieldkg(), data.getActualyieldkg());
            }
        }

        // 构建系列数据
        List<EfficiencyVo.SeriesData> seriesList = new ArrayList<>();
        for (String workshop : workshops) {
            EfficiencyVo.SeriesData series = new EfficiencyVo.SeriesData();
            series.setName(workshop);
            series.setData(new ArrayList<>());

            for (String date : xAxisData) {
                EfficiencyData ed = workshopEfficiencyMap.get(workshop).get(date);
                if (ed != null) {
                    double efficiency = ed.calculateEfficiency();
                    series.getData().add(efficiency);

                    // 调试日志：记录效率计算结果
                    log.info("Efficiency calculated - Workshop: {}, Date: {}, Efficiency: {}%",
                            workshop, date, efficiency);

                } else {
                    series.getData().add(0.0); // 没有数据时设为0
                }
            }
            seriesList.add(series);
        }

        // 构建返回对象
        EfficiencyVo vo = new EfficiencyVo();



        vo.setXAxisData(formatXAxisDates(xAxisData));
        vo.setTitle(workshops);
        vo.setSeries(seriesList);
        vo.setLegendData(workshops);

        return vo;
    }

    /**
     * 获取设备组效率
     *
     * @return
     */
    public GroupEfficiencyVo getGroupProcessEfficiency(String startDate, String endDate) {
        // 1. 查询数据
        List<Shachangsbbanyield> dataList = scKbMapper.selectGroupEfficiency(startDate, endDate);

        // 2. 获取所有日期、班组、工序
        List<String> dates = dataList.stream()
                .map(data -> data.getDay().substring(0, 10))
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        // 定义班组列表，用于设备效率统计的分组维度
        List<String> shifts = Arrays.asList("甲班", "乙班", "丙班");
        // 定义工序列表，用于设备效率统计的分组维度
        List<String> processes = Arrays.asList("梳棉", "头井", "末井", "粗纱", "细纱", "络筒");

        // 3. 初始化数据结构
        Map<String, Map<String, Map<String, EfficiencyData>>> tempData = new HashMap<>();

        for (String date : dates) {
            tempData.put(date, new HashMap<>());
            for (String shift : shifts) {
                tempData.get(date).put(shift, new HashMap<>());
                for (String process : processes) {
                    tempData.get(date).get(shift).put(process, new EfficiencyData());
                }
            }
        }

        // 4. 填充数据
        for (Shachangsbbanyield data : dataList) {
            String date = data.getDay().substring(0, 10);
            String shift = data.getShift();
            String process = "";

            if (!tempData.containsKey(date) ||
                    !tempData.get(date).containsKey(shift) ||
                    !tempData.get(date).get(shift).containsKey(process)) {
                continue;
            }

            EfficiencyData ed = tempData.get(date).get(shift).get(process);

            try {
                BigDecimal theoretical = new BigDecimal(data.getActualyieldkg());
                BigDecimal actual = new BigDecimal(data.getActualyieldkg());

                ed.addTheoretical(theoretical);
                ed.addActual(actual);
            } catch (Exception e) {
                log.error("Invalid data: date={}, shift={}, process={}", date, shift, process, e);
            }
        }

        // 5. 计算效率并转换为最终格式
        Map<String, Map<String, Map<String, Double>>> efficiencyData = new HashMap<>();

        for (String date : dates) {
            efficiencyData.put(date, new HashMap<>());

            for (String shift : shifts) {
                efficiencyData.get(date).put(shift, new HashMap<>());

                for (String process : processes) {
                    EfficiencyData ed = tempData.get(date).get(shift).get(process);
                    double efficiency = ed.calculateEfficiency();

                    // 限制效率在合理范围内
                    if (efficiency > 100) {
                        efficiency = 100.0;
                    } else if (efficiency < 0) {
                        efficiency = 0.0;
                    }

                    efficiencyData.get(date).get(shift).put(process, efficiency);
                }
            }
        }

        // 6. 构建返回对象
        GroupEfficiencyVo vo = new GroupEfficiencyVo();
        vo.setDates(dates);
        vo.setShifts(shifts);
        vo.setProcesses(processes);
        vo.setEfficiencyData(efficiencyData);

        return vo;
    }

    /**
     * 获取设备保养记录
     *
     * @return
     */
    @Override
    public List<MaintenanceRecordDTO> getMaintenanceRecords() {
        return scKbMapper.getMaintenanceRecords();
    }

    @Override
    public List<MaintenanceDataDTO> getDailyStats() {
        return scKbMapper.getDailyMaintenanceStats();
    }

    @Override
    public List<MaintenanceDataDTO> getMonthlyStats() {
        return scKbMapper.getMonthlyMaintenanceStats();
    }

    @Override
    public List<MaintenanceDataDTO> getYearlyStats() {
        return scKbMapper.getYearlyMaintenanceStats();
    }


    /**
     * 获取最近7天的日期列表
     * @return
     */
    private List<String> getDate() {
        LocalDate end = LocalDate.now();
        LocalDate start = end.minusDays(6);
        List<String> dates = new ArrayList<>();
        while (!start.isAfter(end)) {
            dates.add(start.toString()); // 格式为 "yyyy-MM-dd"
            start = start.plusDays(1);
        }
        return dates;
    }

    // 格式化日期为 "M-d" 格式（8-15）
    private List<String> formatXAxisDates(List<String> dates) {
        return dates.stream()
                .map(dateStr -> {
                    try {
                        LocalDate date = LocalDate.parse(dateStr);
                        return date.getMonthValue() + "-" + date.getDayOfMonth();
                    } catch (Exception e) {
                        // 直接操作字符串
                        String month = dateStr.substring(5, 7).replaceFirst("^0", "");
                        String day = dateStr.substring(8, 10).replaceFirst("^0", "");
                        return month + "-" + day;
                    }
                })
                .collect(Collectors.toList());
    }


}

